2019_lewitt_serial_project_1.py

#

SPDX-FileCopyrightText: 2019 Ayman Ghazali SPDX-FileCopyrightText: 2024 AlICe laboratory https://alicelab.be

SPDX-License-Identifier: GPL-3.0-or-later

#

-- coding:Utf8 --

#

SOL Lewitt - Serial project no.1 - Configuration no.3 (MAIN CODE) # Authors: [Ayman Ghazali] # Date: [24.01.2020] # Blender version: [2.8 & hash] # OS: [MacOS Mojave (10.14.6] #

import bpy
import random
#

Cleaning_Scene

#

Cleaning datafile through saving and reopening !!! only works if .blend file previously saved

def reset():
#

helpers

    save = bpy.ops.wm.save_mainfile
    open = bpy.ops.wm.open_mainfile
    path = bpy.data.filepath
#

action

    if path is "":
        save()
        path = bpy.data.filepath
        print(".blend file saved in home directory")

    save(filepath=path)
    open(filepath=path)
#

Delete scene before running script

def delete():
#

helpers

    select = bpy.ops.object.select_all
    delete = bpy.ops.object.delete
#

action

    select(action="SELECT")
    delete(use_global=False)


delete()
#
                        Proximity/progression rule                             #
#

This function generates a grid of dimensions (tuples) following the progressive rule used in Sol Lewitt’s art work

def gen_grid():
#

All possible progressions

    poss = [
        [0, 1, 3, 1],
        [3, 1, 0, 1],
        [0, 1, 0, 1],
        [1, 0, 1, 3],
        [1, 0, 1, 0],
        [1, 3, 1, 0],
        [1, 3, 1, 3],
        [3, 1, 3, 1],
    ]
    random.shuffle(poss)

    i = poss[0][0]
    j = poss[0][1]
    k = poss[0][2]
    l = poss[0][3]

    r = random.choice([0, 1, 2, 3, 4, 5, 6, 7])
    a = poss[r][0]
    b = poss[r][1]
    c = poss[r][2]
    d = poss[r][3]
#

The generated grid

    grid = [
        [(i, a), (i, b), (i, c), (i, d)],
        [(j, a), (j, b), (j, c), (j, d)],
        [(k, a), (k, b), (k, c), (k, d)],
        [(l, a), (l, b), (l, c), (l, d)],
    ]

    return grid


grid = gen_grid()
print("###############################################")
print(grid[0])
print(grid[1])
print(grid[2])
print(grid[3])
print("###############################################")
#
                           Elements of variation                               #
#

Initial variables

add_cube = bpy.ops.mesh.primitive_cube_add
x_sel = 0
y_sel = 0
z_sel = 0
factor = [4, 2, 1, 0.5]
S = False
W = True
#

Defining the element of variation (The cube inside the cube)

#

This function defines the dimensional variations of the bigger geometry (Geometry 1)

def dim_element1(x_sel, y_sel, z_sel, h_sel1, h_sel2, Mat1, factor):
#

Geometry 1

    add_cube(location=(x_sel, y_sel, z_sel))

    if Mat1 == True:
        bpy.ops.object.modifier_add(type="WIREFRAME")
        bpy.context.object.modifiers["Wireframe"].thickness = 0.3
        bpy.context.object.modifiers["Wireframe"].offset = -1

    bpy.ops.object.editmode_toggle()
    bpy.ops.transform.resize(value=(3 * factor, 3 * factor, h_sel1 * factor))
    add_cube(location=(x_sel, y_sel, z_sel))
    bpy.ops.transform.resize(value=(h_sel1 * factor, 3 * factor, 3 * factor))
    add_cube(location=(x_sel, y_sel, z_sel))
    bpy.ops.transform.resize(value=(3 * factor, h_sel1 * factor, 3 * factor))
    bpy.ops.object.editmode_toggle()
#

This function defines the dimensional variations of the smaller gometry (Geometry 2)

def dim_element2(x_sel, y_sel, z_sel, h_sel1, h_sel2, Mat2, factor):
#

Geometry 2

    add_cube(location=(x_sel, y_sel, z_sel))
    if Mat2 == True:
        bpy.ops.object.modifier_add(type="WIREFRAME")
        bpy.context.object.modifiers["Wireframe"].thickness = 0.3
        bpy.context.object.modifiers["Wireframe"].offset = -1
    bpy.ops.object.editmode_toggle()
    bpy.ops.transform.resize(value=(1 * factor, 1 * factor, h_sel2 * factor))
    add_cube(location=(x_sel, y_sel, z_sel))
    bpy.ops.transform.resize(value=(h_sel2 * factor, 1 * factor, 1 * factor))
    add_cube(location=(x_sel, y_sel, z_sel))
    bpy.ops.transform.resize(value=(1 * factor, h_sel2 * factor, 1 * factor))
    bpy.ops.object.editmode_toggle()
#

This function creates the set of elements and makes them vary according to their position

def add_set(x_sel, y_sel, z_sel, tup, factor, Mat1, Mat2):
#

Defining variables

    h_sel1 = tup[0]
    h_sel2 = tup[1]
    dim_element1(x_sel, y_sel, z_sel, h_sel1, h_sel2, Mat1, factor)
    dim_element2(x_sel, y_sel, z_sel, h_sel1, h_sel2, Mat2, factor)


dim = [4, 2, 1, 0.5]
#

This function calculates the reccursive sequence that helps putting geometries with decreasing/increasing sizes next to eachother (sharing the same faces)

def term(n):
#
    if n == 0:
        return 0
    else:
        res = term(n - 1) + (dim[n] + dim[n - 1]) / 2
        return res
#

This function Generates the 1/4 cube structure containing geometries placed according to Sol Lewitt’s rule and varying in 3 directional ways (x,y,z)

def generate_structure(locx, locy, locz, Mat1, Mat2):
#

starting element :

    add_set(
        locx + 6 * (term(0) + 2),
        locy + 6 * dim[0] / 2,
        locz + 6 * dim[0] / 2,
        grid[1][1],
        dim[0],
        Mat1,
        Mat2,
    )
#

resulting structure in x,y,z axes (Global) :

    add_set(
        locx + 6 * term(1) + 12,
        locy + 6 * dim[1] / 2,
        locz + 6 * dim[1] / 2,
        grid[1][2],
        dim[1],
        not Mat1,
        not Mat2,
    )
    add_set(
        locx + 6 * dim[1] / 2,
        locy + 6 * term(1) + 12,
        locz + 6 * dim[1] / 2,
        grid[2][1],
        dim[1],
        not Mat1,
        not Mat2,
    )
    add_set(
        locx + 6 * dim[1] / 2,
        locy + 6 * dim[1] / 2,
        locz + 6 * term(1) + 12,
        grid[2][2],
        dim[1],
        not Mat1,
        not Mat2,
    )
#

resulting structure in x,y,z axes (local) : Alternatives in x :

    add_set(
        locx + 6 * term(2) + 12,
        locy + 6 * dim[2] / 2,
        locz + 6 * dim[2] / 2,
        grid[1][3],
        dim[2],
        Mat1,
        Mat2,
    )
    add_set(
        locx + 27,
        locy + 6 * dim[2] / 2,
        locz + term(2) + 10.5,
        grid[0][3],
        dim[2],
        Mat1,
        Mat2,
    )
    add_set(
        locx + 27,
        locy + term(2) + 10.5,
        locz + 6 * dim[2] / 2,
        grid[0][2],
        dim[2],
        Mat1,
        Mat2,
    )
#

Alternatives in y :

    add_set(
        locx + 6 * dim[2] / 2,
        locy + 6 * term(2) + 12,
        locz + 6 * dim[2] / 2,
        grid[3][1],
        dim[2],
        Mat1,
        Mat2,
    )
    add_set(
        locx + 6 * dim[2] / 2,
        locy + 27,
        locz + term(2) + 10.5,
        grid[3][0],
        dim[2],
        Mat1,
        Mat2,
    )
    add_set(
        locx + term(2) + 10.5,
        locy + 27,
        locz + 6 * dim[2] / 2,
        grid[2][0],
        dim[2],
        Mat1,
        Mat2,
    )
#

Alternatives in z :

    add_set(
        locx + 6 * dim[2] / 2,
        locy + 6 * dim[2] / 2,
        locz + 6 * term(2) + 12,
        grid[3][3],
        dim[2],
        Mat1,
        Mat2,
    )
    add_set(
        locx + term(2) + 10.5,
        locy + 6 * dim[2] / 2,
        locz + 27,
        grid[2][3],
        dim[2],
        Mat1,
        Mat2,
    )
    add_set(
        locx + 6 * dim[2] / 2,
        locy + term(2) + 10.5,
        locz + 27,
        grid[3][2],
        dim[2],
        Mat1,
        Mat2,
    )
#

1/4 Cube structure (1)

generate_structure(0, 0, 0, W, S)
#

1/4 Cube structure (2)

generate_structure(50, 0, 0, S, W)
#

1/4 Cube structure (3)

generate_structure(100, 0, 0, S, S)
#

1/4 Cube structure (4)

generate_structure(150, 0, 0, W, W)
#

reset()